# -*- coding: UTF-8 -*-
# ！/usr/bin/env python3

import json
from log_helper import logger
from deepdiff import DeepDiff


def check_code_and_msg(resp, expected_msg=None, expected_code=200):
    """
    验证响应字典是否符合预期的状态码和消息内容。

    :param resp: 响应字典，应包含 'code' 和 'msg'/'message' 字段
    :param expected_msg: 预期的消息内容，如果提供则验证消息字段
    :param expected_code: 预期的状态码，默认为200
    :return: 验证后的响应字典（如果验证通过）
    :raises: AssertionError 当验证失败时抛出
    """
    # 验证状态码
    if expected_code != resp.get('code'):
        assert False, f"预期状态码 {expected_code}，但实际为 {resp.get('code')}"

    # 如果提供了预期消息，则验证消息内容
    if expected_msg is not None:
        # 检查 'msg' 或 'message' 字段是否匹配预期消息
        if not any(expected_msg == resp.get(key) for key in ['msg', 'message']):
            assert False, (
                f"预期消息 '{expected_msg}'，但实际 'msg': '{resp.get('msg')}' "
                f"且 'message': '{resp.get('message')}'"
            )
    return resp

def checkEqual(actualVal, expectedVal, errMsg=None, onlyLogError=False):
    '''
    检查实际结果是否与预期匹配
    :param actualVal: 实际值，可以是字符串或列表
    :param expectedVal: 预期值，可以是字符串或列表
    :param errMsg: 自定义错误消息
    :param onlyLogError: 是否仅记录错误而不抛出异常
    '''
    logger().info("Check the value '%s' with '%s'" % (toStr(actualVal), toStr(expectedVal)))

    if errMsg is None:
        errMsg = "Expected '%s' is not as actual '%s'" % (toStr(expectedVal), toStr(actualVal))

    if actualVal != expectedVal:
        logger().info(errMsg)
        if onlyLogError:
            return False
        else:
            raise AssertionError(errMsg)
    return True


def check_zh_equal(actualVal, expectedVal, errMsg=None, onlyLogError=False):
    '''
    检查实际结果是否与预期匹配（中文比较）
    :param actualVal: 实际值，可以是字符串
    :param expectedVal: 预期值，可以是字符串
    :param errMsg: 自定义错误消息
    :param onlyLogError: 是否仅记录错误而不抛出异常
    '''
    logger().info("Check the value '%s' with '%s'" % ((actualVal), (expectedVal)))
    if all(isinstance(i, str) for i in [actualVal, expectedVal]):
        if expectedVal in actualVal:
            return True
    diff = DeepDiff(expectedVal, actualVal, ignore_order=True)
    if not diff or ("dictionary_item_added" in diff and "values_changed" not in diff):
        return True
    if "values_changed" in diff:
        old_value = diff['values_changed']['root']['old_value']
        new_value = diff['values_changed']['root']['new_value']
        if all(key in new_value and new_value[key] == old_value[key] for key in old_value):
            return True
        errMsg = f"预期结果 '{expectedVal}' 与实际结果 '{actualVal}' 不匹配"
        raise AssertionError(errMsg)

    else:
        if errMsg is None:
            errMsg = f"预期结果 '{expectedVal}' 与实际结果 '{actualVal}' 不匹配"
        if onlyLogError:
            print(errMsg)
            return False
        else:
            raise AssertionError(errMsg)


def toStr(strItem):
    '''
    将对象转换为字符串，如果对象可以转换为字符串，则返回字符串类型；否则，直接返回原始对象
    :param object strItem: 需要转换的对象
    :param exampleParam: 示例参数，可以忽略
    :return string: 转换后的字符串或者原始对象
    '''
    try:
        return str(strItem)
    except:
        return strItem


def check_isdata(resp):
    """
    验证响应数据是否有效

    参数:
        resp (dict): 包含响应数据的字典

    断言:
        - 响应数据不为空 (None)
        - 响应数据长度大于0

    返回:
        dict: 原始响应数据

    异常:
        AssertionError: 如果响应数据为空或长度为0
    """
    assert resp['data'] is not None and len(resp['data']) > 0, "Data is empty or None"
    return resp


def check_isdict(resp: dict) -> dict:
    """
    验证响应数据类型为字典，并且包含'data'键。

    参数：
    - resp: 响应数据的字典。

    返回：
    - 如果验证通过，返回传入的字典。

    抛出：
    - TypeError: 如果resp不是字典。
    - KeyError: 如果字典中不包含'data'键。
    """
    if not isinstance(resp, dict):
        raise TypeError("返回结果应该是一个字典")

    if 'data' not in resp:
        raise KeyError("返回的字典中应该包含'data'键")

    return resp

_cache_config = {}
_goods_cache = {}
_cache = {}

class CacheHandler:

    @staticmethod
    def get_cache():
        return _cache_config
    @staticmethod
    def set_goods_cache(*, cache_name, value):
        _goods_cache[cache_name] = value
    @staticmethod
    def set_cache(*, cache_name, value):
        _cache_config[cache_name] = value

    @staticmethod
    def remove_cache(*, cache_name):
        if cache_name in _cache_config:
            _cache_config.pop(cache_name, None)

    @staticmethod
    def get_cache_value(*,cache_name):
        try:
            if cache_name in _cache_config:
                return _cache_config[cache_name]
            else:
                return f'{cache_name}未找到'
        except KeyError as e:
            raise KeyError(f'{cache_name}未找到') from e

    @staticmethod
    def get_goods_cache_value(*, cache_name):
        try:
            if cache_name in _goods_cache:
                return _goods_cache[cache_name]
            else:
                return f'{cache_name}未找到'
        except KeyError as e:
            raise KeyError(f'{cache_name}未找到') from e

    @staticmethod
    def get_all_cache_value(*, cache_name):
        try:
            if cache_name in _cache:
                return _cache[cache_name]
            else:
                return f'{cache_name}未找到'
        except KeyError as e:
            raise KeyError(f'{cache_name}未找到') from e

    @staticmethod
    def set_all_cache_value(*, cache_name, value):
        _cache[cache_name] = value


def check_response(response_data, expected_code, expected_msg, expected_success):
    """
    校验响应数据中的 code、msg 和 success 字段是否符合预期。
    :param response_data: 响应数据（字典）
    :param expected_code: 预期的 code 值
    :param expected_msg: 预期的 msg 值
    :param expected_success: 预期的 success 值
    """
    # 校验 code 字段
    assert response_data['code'] == expected_code, (
        f"code 不匹配：预期值为 {expected_code}，实际值为 {response_data['code']}"
    )

    # 校验 msg 字段
    assert response_data['msg'] == expected_msg, (
        f"msg 不匹配：预期值为 {expected_msg}，实际值为 {response_data['msg']}"
    )

    # 校验 success 字段
    assert response_data['success'] == expected_success, (
        f"success 不匹配：预期值为 {expected_success}，实际值为 {response_data['success']}"
    )
